package com.xingfei.blog.controller;

import com.alibaba.fastjson.JSONObject;
import com.xingfei.blog.common.utils.DateUtil;
import com.xingfei.blog.common.utils.ImageUtils;
import com.xingfei.blog.common.utils.MyFileUtil;
import com.xingfei.blog.common.vo.JsonResult;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * 图片上传控制器
 *
 * @author: chenxingfei
 * @time: 2017/2/7  15:39
 * To change this template use File | Settings | File Templates.
 */
@Scope("prototype")
@Controller
@RequestMapping("/uploadFile")
public class UploadController {


    private Logger logger = LoggerFactory.getLogger(UploadController.class);

    public static final String IMG_TYPE_AVATAR = "avatar"; // 头像图片

    @Value("${file.path}")
    private String filePath;

    /**
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("/ruok")
    public String imok(HttpServletRequest request
            , HttpServletResponse response) {
        return "imok";
    }

    /**
     * 删除图片
     * </p>
     *
     * @param path     图片相对路径(如:file/xxx/xxx.png)
     * @param request
     * @param response
     */
    @ResponseBody
    @RequestMapping("/delImgByPath")
    public String delImgByPath(String path
            , HttpServletRequest request
            , HttpServletResponse response) {
        try {
            logger.info("del img path: " + path);
            String flag = "0";
            if (StringUtils.isNotBlank(path)) {
                String dir = filePath + File.separator + path;
                boolean success = (new File(dir)).delete();
                if (success) {
                    flag = "1";
                }
            }
            return flag;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        }
        return "0";
    }

    /**
     * 删除图片,支持跨域
     * </p>
     *
     * @param dir          图片相对路径(如:file/xxx/xxx.png)
     * @param jsoncallback jsonp
     * @param request
     * @param response
     */
    @ResponseBody
    @RequestMapping("/delImgByDir")
    public void delImgByPath(String dir
            , String jsoncallback
            , HttpServletRequest request
            , HttpServletResponse response) {
        logger.info("del img dir: " + dir);
        String flag = "0";
        if (StringUtils.isNotBlank(dir)) {
            String path = filePath + File.separator + dir;
            boolean success = (new File(path)).delete();
            if (success) {
                flag = "1";
            }
        }
        response.setContentType("text/html; charset=utf-8");
        ServletOutputStream sos = null;
        try {
            sos = response.getOutputStream();
            JSONObject writer = new JSONObject();
            String content = writer.getString(flag);
            content = jsoncallback + "(" + content + ")";
            sos.write(content.getBytes("utf-8"));
        } catch (Exception ee) {
            ee.printStackTrace();
            logger.error(ee.getMessage());
        } finally {
            if (sos != null)
                try {
                    sos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    logger.error(e.getMessage());
                }
        }
    }

    /**
     * 上传图片，返回值支持跨域
     * </p>
     *
     * @param type     图片类型,路径组成部分
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("/uploadCross")
    public void uploadImgCross(String type
            , HttpServletRequest request
            , HttpServletResponse response
            , @RequestParam(value = "file", required = false) MultipartFile file
    ) {
        try {
            String path = null;
            if (StringUtils.isNotBlank(type)) {
                path = this.saveImgFileByType(type, file);
                response.getWriter().write(path);
                response.setHeader("Access-Control-Allow-Origin", "*");
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        }
    }

    /**
     * 上传视频
     * </p>
     *
     * @param type     视频类型,路径组成部分
     * @param request
     * @param response
     * @return
     */
    @ResponseBody
    @RequestMapping("/uploadVideoByType")
    public String uploadVideoByType(String type
            , MultipartHttpServletRequest request
            , HttpServletResponse response) {
        try {
            return this.saveImgByType(Boolean.FALSE, null, type, request, response);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            return null;
        }
    }

    /**
     * 上传base64编码的图片
     * </p>
     *
     * @param imgStr   base64编码的图片字符串
     * @param imgType  图片类型,组成图片路径
     * @param request
     * @param response
     * @return
     */
    @SuppressWarnings("restriction")
    @ResponseBody
    @RequestMapping("/uploadImgStr")
    public String uploadImgStr(String imgStr
            , String imgType
            , HttpServletRequest request
            , HttpServletResponse response) {
        FileOutputStream output = null;
        try {
            if (StringUtils.isBlank(imgStr) || StringUtils.isBlank(imgType)) {
                return null;
            }
            sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
            byte[] img = decoder.decodeBuffer(imgStr);
            if (img == null || img.length <= 0) {
                return null;
            }
            String imgPath = "files" + File.separator + getImagePath(imgType) + ".png"; // 获得目录下的相对路径
            // 图片绝对路径
            String absolute = filePath + File.separator + imgPath;
            if (StringUtils.isBlank(absolute)) {
                return null;
            }
            String filePath = absolute.substring(0, absolute.lastIndexOf(File.separator) + 1);
            // 保存图片
            File file = new File(filePath);
            if (!(file.exists() && file.isDirectory())) {
                file.mkdirs();
            }
            output = new FileOutputStream(new File(absolute));
            output.write(img);
            return imgPath;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (output != null) {
                try {
                    output.close();
                } catch (IOException e) {
                    logger.error(e.getMessage());
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    /**
     * 上传有相对路径的图片
     * </p>
     *
     * @param imgPath  图片相对路径
     * @param request
     * @param response
     * @return
     */
    @ResponseBody
    @RequestMapping("/addImg")
    public String uploadImage(String imgPath
            , MultipartHttpServletRequest request
            , HttpServletResponse response) {

        if (StringUtils.isNotBlank(imgPath)) {
            List<String> listStr = Arrays.asList(imgPath.split("#"));
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < listStr.size(); i++) {
                sb.append(listStr.get(i));
                if (i < listStr.size() - 1) {
                    sb.append(File.separator);
                }
            }
            imgPath = sb.toString().replaceAll("\"", "");
        }
        String flag = saveImgByType(Boolean.TRUE, imgPath, null, request, response);
        if (StringUtils.isBlank(flag)) {
            // 失败
            return "0";
        } else {
            // 成功
            return "1";
        }
    }


    /**
     * 上传头像图片
     * </p>
     *
     * @param request
     * @param response
     * @return
     */
    @ResponseBody
    @RequestMapping("/avatarImg")
    public JsonResult uploadAvatarImage(MultipartHttpServletRequest request, HttpServletResponse response) {
        try {
            System.out.println("--------------------" + filePath);
            String path = saveImgByType(Boolean.TRUE, null, IMG_TYPE_AVATAR, request, response);
            if (StringUtils.isBlank(path)) {
                return buildJsonResult("417", path, Boolean.FALSE);
            } else {
                return buildJsonResult("0", path, Boolean.FALSE);
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
            return buildJsonResult("500", null, Boolean.FALSE);
        }
    }


    /**
     * 上传图片并返回相对路径 <br>
     *
     * @param request
     * @param response
     */
    @RequestMapping("/getImgPath")
    @ResponseBody
    public String uploadImageByPath(MultipartHttpServletRequest request, HttpServletResponse response, String imgType) {
        try {
            String imgPath = saveImgByType(Boolean.TRUE, null, imgType, request, response);
            return imgPath;
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return null;
    }

    /**
     * 上传图片并返回相对路径
     * <br>
     *
     * @param imgType  图片类型
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("/getImgPathByType")
    @ResponseBody
    public String uploadImageByType(String imgType
            , MultipartHttpServletRequest request
            , HttpServletResponse response) {
        //ServletOutputStream sos=null;
        try {
            if (StringUtils.isBlank(imgType)) {
                return null;
            }
            String imgPath = saveImgByType(Boolean.TRUE, null, imgType, request, response);
            //response.setContentType("text/html; charset=utf-8");
            //sos = response.getOutputStream();
            //sos.write(imgPath.getBytes("utf-8"));
            return imgPath;
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
//		finally {
//			if(sos != null){
//				try {
//					sos.close();
//				} catch (IOException e) {
//					e.printStackTrace();
//				}
//			}
//		}
        return null;
    }

    /**
     * 上传图片并返回相对路径
     * </p>
     *
     * @param isDefault 是否是商品默认图片
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("/getProductImgPath")
    @ResponseBody
    public String uploadProductImageByPath(boolean isDefault
            , MultipartHttpServletRequest request
            , HttpServletResponse response, String imgType) {
        try {
            int width = 140;
            int height = 100;
            String imgPath = this.saveImgAndGenerateSmallImgByWidthHeigh(isDefault, width, height, imgType, request, response);
            return imgPath;
        } catch (Exception e) {
            logger.error(e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 保存图片到本地
     * </p>
     *
     * @param type 图片类型
     * @param mpf  图片
     * @return
     */
    private String saveImgFileByType(String type, MultipartFile mpf) {
        logger.info("upload" + type + " img start");
        if (mpf.isEmpty()) {
            logger.error("upload" + type + " img is null------上传文件为空");
            return null;
        }
        try {
            //
            int imgSzie = mpf.getInputStream().available();
            // 获取文件名
            String fileName = mpf.getOriginalFilename();
            if (StringUtils.isBlank(fileName)) {
                logger.error("文件名为空");
                return null;
            }
            // 文件后缀
            String suffix = ".png";
            if (mpf.getSize() / 1000 <= 30000 && mpf.getSize() == imgSzie) {
                // 图片相对路径
                String imgPath = "files" + File.separator + getImagePath(type) + suffix; // 获得目录下的相对路径
                // 图片绝对路径
                String originalName = filePath + File.separator + imgPath;
                // 保存图片
                MyFileUtil.saveInputStreamToFile(mpf.getInputStream(), originalName);
                logger.info(imgPath + " 图片上传成功");
                return imgPath;
            } else {
                if (mpf.getSize() != imgSzie) {
                    logger.error("#######图片上传失败，服务器获取到图片大小(字节): " + mpf.getSize() + ", 上传图片实际大小(字节): " + imgSzie);
                } else {
                    logger.error("单张照片不得超过30M");
                }
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 保存图片到本地
     * </p>
     *
     * @param isDefaultSuffix 是否使用默认后缀名
     * @param path            图片相对路径
     * @param type            图片类型
     * @param request
     * @param response
     * @return
     */
    private String saveImgByType(boolean isDefaultSuffix, String path, String type, MultipartHttpServletRequest request,
                                 HttpServletResponse response) {
//		if (this.isUploadBlank(request)) {
//			logger.error("upload" + type + " img is null------上传文件为空");
//			return "";
//		}
        logger.info("upload" + type + " img start path: " + path);
        Iterator<String> itr = request.getFileNames();
        MultipartFile mpf = null;
        while (itr.hasNext()) {
            try {
                mpf = request.getFile(itr.next());
                if (mpf.isEmpty()) {
                    logger.error("upload" + type + " img is null------上传文件为空");
                    return null;
                }
                //
                int imgSzie = mpf.getInputStream().available();
                // 获取文件名
                String fileName = mpf.getOriginalFilename();
                if (StringUtils.isBlank(fileName)) {
                    logger.error("文件名为空");
                    return null;
                }
                // 文件后缀
                String suffix = ".png";
                if (!isDefaultSuffix) {
                    suffix = fileName.substring(fileName.lastIndexOf("."));
                }
                if (mpf.getSize() / 1000 <= 30000 && mpf.getSize() == imgSzie) {
                    // 图片相对路径
                    String imgPath = path;
                    if (StringUtils.isBlank(imgPath)) {
                        imgPath = "files" + File.separator + getImagePath(type) + suffix; // 获得目录下的相对路径
                    }
                    // 图片绝对路径
                    String originalName = filePath + File.separator + imgPath;
                    // 保存图片
                    MyFileUtil.saveInputStreamToFile(mpf.getInputStream(), originalName);
                    logger.info(imgPath + " 图片上传成功");
                    return imgPath;
                } else {
                    if (mpf.getSize() != imgSzie) {
                        logger.error("#######图片上传失败，服务器获取到图片大小(字节): " + mpf.getSize() + ", 上传图片实际大小(字节): " + imgSzie);
                    } else {
                        logger.error("单张照片不得超过30M");
                    }
                    return null;
                }
            } catch (IOException e) {
                logger.error(e.getMessage());
                return null;
            }
        }
        logger.error("没有上传的图片");
        return null;
    }

    /**
     * 保存图片到本地并生成指定宽高的缩略图
     * </p>
     *
     * @param isCut    是否生成缩略图
     * @param width    宽
     * @param height   高
     * @param type     图片类型
     * @param request
     * @param response
     * @return
     */
    private String saveImgAndGenerateSmallImgByWidthHeigh(boolean isCut
            , int width
            , int height
            , String type
            , MultipartHttpServletRequest request,
                                                          HttpServletResponse response) {
        logger.info("upload" + type + " img start");
        Iterator<String> itr = request.getFileNames();
        MultipartFile mpf = null;
        while (itr.hasNext()) {
            try {
                mpf = request.getFile(itr.next());
                if (mpf.isEmpty()) {
                    logger.error("upload" + type + " img is null------上传文件为空");
                    return null;
                }
                //
                int imgSzie = mpf.getInputStream().available();
                // 获取文件名
                String fileName = mpf.getOriginalFilename();
                if (StringUtils.isBlank(fileName)) {
                    logger.error("文件名为空");
                    return null;
                }
                // 文件后缀
                String suffix = ".png";
                if (mpf.getSize() / 1000 <= 30000 && mpf.getSize() == imgSzie) {
                    // 图片相对路径
                    String imgPath = "files" + File.separator + getImagePath(type) + suffix; // 获得目录下的相对路径
                    // 图片绝对路径
                    String originalName = filePath + File.separator + imgPath;
                    // 保存图片
                    MyFileUtil.saveInputStreamToFile(mpf.getInputStream(), originalName);

                    // 只针对默认商品图片进行压缩
                    if (isCut) {
                        // 获取缩略图路径
                        String smallImgPath = getSmallImgNameByHeightAndWidth(originalName, height, width);
                        if (StringUtils.isNotBlank(smallImgPath)) {
                            // 临时存储变量
//							String tempPath = filePath + File.separator + "temp" + File.separator
//									+ System.currentTimeMillis() + ".png";
//							String parentPath = filePath + File.separator + "temp" + File.separator;
//							File parentFile = new File(parentPath);
//							if (!(parentFile.exists() && parentFile.isDirectory())) {
//								parentFile.mkdir();
//							}
                            ImageUtils.scale(originalName, smallImgPath, 4, false, 140, 100);
//							new File(tempPath).deleteOnExit();
                        }
                    }
                    logger.info(imgPath + " 图片上传成功");
                    return imgPath;
                } else {
                    if (mpf.getSize() != imgSzie) {
                        logger.error("#######图片上传失败，服务器获取到图片大小(字节): " + mpf.getSize() + ", 上传图片实际大小(字节): " + imgSzie);
                    } else {
                        logger.error("单张照片不得超过30M");
                    }
                    return null;
                }
            } catch (IOException e) {
                logger.error(e.getMessage());
                e.printStackTrace();
                return null;
            }
        }
        logger.error("没有上传的图片");
        return null;
    }

    /**
     * 判断上传文件是否为空 <br>
     * true：为空，false：不为空 <br>
     *
     * @param request
     * @return
     */
    private boolean isUploadBlank(MultipartHttpServletRequest request) {
        Map<String, MultipartFile> fileMap = request.getFileMap();
        Set<String> keys = fileMap.keySet();
        if (keys == null || keys.size() <= 0) {
            return Boolean.TRUE;
        } else {
            return Boolean.FALSE;
        }
    }

    /**
     * 获取缩略图路径
     * <br>
     *
     * @param originalName
     * @return
     */
    private String getSmallImgName(String originalName) {
        if (StringUtils.isBlank(originalName))
            return null;
        int index = originalName.lastIndexOf(".");
        String smallPath = "";
        if (index != -1) {
            String prefix = originalName.substring(0, index);
            String suffix = originalName.substring(index + 1);
            smallPath = prefix + "_" + ImageUtils.SMALL_IMG_WIDTH + "x" + ImageUtils.SMALL_IMG_HEIGHT + "." + suffix;
        }
        return smallPath;
    }

    /**
     * 获取缩略图路径
     * <br>
     *
     * @param originalName
     * @param height       高度
     * @param width        宽度
     * @return
     */
    private String getSmallImgNameByHeightAndWidth(String originalName, int height, int width) {
        if (StringUtils.isBlank(originalName)) {
            return null;
        }
        int index = originalName.lastIndexOf(".");
        String smallPath = "";
        if (index != -1) {
            String prefix = originalName.substring(0, index);
            String suffix = originalName.substring(index + 1);
            smallPath = prefix + "_" + width + "x" + height + "." + suffix;
        }
        return smallPath;
    }

    /**
     * 拼接图片相对路径
     * </p>
     *
     * @param type
     * @return
     */
    private static String getImagePath(String type) {
        // 图片相对路径生成规则：类型/日期/时间戳+3位唯一标识
        StringBuilder sb = new StringBuilder();
        sb.append(type).append(File.separator).append(DateUtil.dateToString(new Date(), "yyyyMMdd"))
                .append(File.separator);
        sb.append(System.currentTimeMillis());
        // TODO获取三位唯一标识
        return sb.toString();
    }

    /**
     * 封装返回结果集
     * </br>
     *
     * @param code
     * @param path
     * @param isencrypt
     * @return
     */
    private JsonResult buildJsonResult(String code, String path, boolean isencrypt) {
        JsonResult js = new JsonResult();
        js.setData(path);
        // 操作成功
        js.setErrorCode(code);
        js.setEncrypt(isencrypt);
        js.setErrorMsg(null);
        return js;
    }

    /**
     * weibo/qq头像下载接口
     */
    @RequestMapping("/uploadByUrl")
    @ResponseBody
    public String uploadPicturByUrl(@RequestParam String remoteUrl){
        logger.info("request: /uploadByUrl,remoteUrl:"+remoteUrl);
        try {
            URL url = new URL(remoteUrl);
            //打开和URL之间的连接
            HttpURLConnection http = (HttpURLConnection) url.openConnection();
            //设置通用的请求属性
            http.setRequestMethod("GET");
            http.setRequestProperty("accept", "*/*");
            http.setRequestProperty("connection", "Keep-Alive");
            http.setRequestProperty("user-agent",
                    "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
            http.setConnectTimeout(10000);
            //建立实际的连接
            http.connect();
            //文件后缀
            String suffix = ".png";
            String suffix2 = remoteUrl.subSequence(remoteUrl.lastIndexOf("."), remoteUrl.length())+"";
            if(suffix2!=null){
                if(suffix2.equalsIgnoreCase(".jpg")){
                    suffix = suffix2;
                }
            }
            //图片相对路径
            String imgPath= null;
            if (StringUtils.isBlank(imgPath)) {
                imgPath = "files" + File.separator + getImagePath(IMG_TYPE_AVATAR) + suffix; // 获得目录下的相对路径
            }
            //图片绝对路径
            String originalName = filePath + File.separator + imgPath;
            //本地存储
            File file = new File(originalName);
            FileUtils.copyURLToFile(url, file);
            logger.info(imgPath + " 图片上传成功");
            return imgPath;
        }catch (Exception e) {
            System.out.println("发送GET请求出现异常！" + e);
            logger.error("/uploadByUrl error:"+e.toString());
            e.printStackTrace();
        }
        return null;
    }
}
